-
-
Notifications
You must be signed in to change notification settings - Fork 312
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Plugin and Extension System #834
base: develop
Are you sure you want to change the base?
Conversation
396bcfb
to
4274218
Compare
e9eed75
to
fd6ddf9
Compare
81eb5bc
to
7034499
Compare
I had a first high-level look at the plugin system. Here are my first thoughts.
I hope a tighter integration will save us from other problems, as we are already having with the config system, where I feel that current proposed changes open quite some edge cases that will be weird and hard to nicely handle with a good user experience. In my use case scenarios, plugins are a predominantly permanent configuration, so I would not enable/disable them via a config flag, but would just use the plugins config file, which is the first thing that is loaded. Also, plugins should be either signed by Safing, or dev mode needs to be active. Loaded plugins themselves could be nicely shown on the dashboard, including some additional information about them. Loading plugins distributed by Safing could be neatly hidden in the quick search bar - metadata about them distributed via the intel-data repo with other metadata files. Question: How would we handle a plugin that depends on the SPN or other modules that the user can turn on and off? |
Plugins would be really nice to have tbh |
🚀 This PR adds support for external Plugins to the Portmaster 🚀
Notes For Reviewers
The config handling part of the plugin system requires a fix in portbase: safing/portbase#185
Roughly the following packages have been created:
plugin
: contains the whole plugin system and portbase moduleplugin/shared/*
: contains code that must be imported by the Portmaster and each plugin instance. It defines the different plugin types and implements the GRPC Server and Client codeplugin/shared/proto
: Go-Source files inplugin/shared/proto
are auto-generated using the protobuf compiler and it's GRPC plugin. Just review the*.proto
files in there and ignore all the*.pb.go
files.plugin/internal
: contains internal stuff that should only be used by the Portmaster and not imported by plugins (to avoid a huge dependency on Portmaster code)plugin/loader
: contains the plugin loader and the lifecycle management code for pluginsplugin/framework
: provides a utility framework for writing plugins without the need to handle a lot of boilerplate code.Introduction
The plugin system is based on hashicorp/go-plugin and uses a sub-process architecture where the plugin host (the Portmaster)
and plugins communicate via gRPC on a localhost/Unix-Socket HTTP/2 connection.
Plugin Types
The package defines a couple of different types that plugin authors may
implement depending on their planned feature set:
Decider Plugins
"decider"
A decider plugin is used by the firewall system to decide if a connection
or DNS request is allowed, blocked or routed through the SPN.
Reporter Plugins
"reporter"
A reporter plugin is notified whenever the firewall found a decision
on a new connection or DNS request. Reporter plugins may be used to store
connection history in places not directly supported by the Portmaster.
Resolver Plugins
"resolver"
A resolver plugin is called when the Portmaster tries to resolve a DNS
query. Resolver plugins are called before the actual resolvers configured
in the Portmaster are queried.
Capabilities
In addition to the plugin types available plugins also have access to the
following Portmaster systems:
Config System:
Plugins can register custom configuration options that will show up in the
Portmaster user interface and can watch for changes to those configuration options.
By default, plugins are restricted to only access configuration options they registered
themselves (that is, configuration keys are always prefixed with "plugins/").
If a plugin is marked as privileged in the JSON configuration file the plugin may access all
configuration options registered in the Portmaster, even internal configuration options.
Plugin authors should be really careful when using or working with Portmaster internal
options as there is no guarantee of their availability and might be changed with any
Portmaster release.
Notification System:
Plugins may display custom notifications to the user with support for notification
actions. Plugins may also "take-over" notifications and can present the to the user
different ways (like pushing to a mobile phone).
Plugin developers must make sure to not take-over notifications whose defined actions
cannot be supported by the plugin implementation. That is, most actions defined in the
proto package are meant to be displayed and executed by the User Interface. An
exception to this, for example, is the Webhook action which may easily implemented
by plugins as well.
Plugin Manager:
Plugins that are configured as privileged in the JSON configuration file also get access
to the plugin management system of Portmaster. That is, privileged plugins may register,
start and stop or remove additional plugins at the Portmaster.
This feature is mainly designed so the Portmaster development community is capable of
implementing
third-party plugin registries that automate the installation and management of plugins.
Configuration
The plugin system first needs to be enabled by the user. A new subsystem is created for the plugin system that is visible in
Developer Mode
when the Feature Stability is set toExperimental
.Afterwards, place your plugins (the binaries) into the plugins folder in the Portmaster installation directory. On linux, this is normally somewhere at
/opt/safing/portmaster/plugins
. That's the only path the plugin loader searches for those executables right now.Next, enable your plugin by creating/editing
/opt/safing/portmaster/plugins.json
and add an entry for your plugin:Examples
Custom Decider
The following is a simple example of a
decider
plugin:Next, build the plugin (
go build .
) and place the binary (let's saymy-plugin
) into/opt/safing/portmaster/plugins
. Finally, make sure the plugins configuration array in/opt/safing/portmaster/plugins.json
contains the follwing:Available Plugins
You can also check out some of the plugins I already created when implementing and testing the Plugin System (this list will be extended in the next days when I start pushing the plugins to github):
DISCLAIMER: none of the following plugins are offical Safing products. Please do not report issues with those plugins in the offical Safing repositories. Rather post the issue in the plugin repositories and I'll try to take care :)
traefik/yaegi
.